home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / technical documentation / develop / develop issue 26 / develop issue 26 code / truffles - display mgr. / sprocket / sources / menubar.cp < prev    next >
Encoding:
Text File  |  1996-01-02  |  7.8 KB  |  364 lines

  1. /*
  2.     File:        Menu.cp
  3.  
  4.     Contains:    A MenuBar class deliberately designed to resemble
  5.                 ODMenuBar from OpenDoc™
  6.  
  7.     Written by: Dave Falkenburg
  8.  
  9.     Copyright:    © 1994-95 by Dave Falkenburg, all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.      
  13.          <3>     1/24/95    DRF        Finished implementing resource-based command registration (CMNU
  14.                                     support).
  15.          <2>     1/20/95    DRF        Implemented GetNewMenuBar. GetMenuFromCMNU is next.
  16.          <1>      1/3/95    DRF        First checked in.
  17.  */
  18.  
  19. #include    "MenuBar.h"
  20. #include    <Resources.h>
  21. #include    <Errors.h>
  22.  
  23.     inline UInt32 BuildKey(UInt16 hiword, UInt16 loword)
  24.     {
  25.         return (((UInt32) hiword << 16) | loword);
  26.     }
  27.  
  28. TMenuItemTable::CompareResult
  29. TMenuItemTable::Compare(ArrayElementPtr element1,ArrayElementPtr element2)
  30.     {
  31.     UInt32    key1 = BuildKey(((MenuMapping *) element1)->fMenu, ((MenuMapping *) element1)->fItem);
  32.     UInt32    key2 = BuildKey(((MenuMapping *) element2)->fMenu, ((MenuMapping *) element2)->fItem);
  33.     
  34.     return    (key2 - key1);
  35.     }
  36.  
  37.  
  38. TMenuCommandTable::CompareResult
  39. TMenuCommandTable::Compare(ArrayElementPtr element1,ArrayElementPtr element2)
  40.     {
  41.     return (((MenuMapping *) element2)->fCommand - ((MenuMapping *) element1)->fCommand);
  42.     }
  43.  
  44.  
  45. OSErr
  46. TMenuBar::GetNewMenuBar(short whichMBAR)
  47.     {
  48.     MenuBarResource ** mbarResource = (MenuBarResource **) GetResource('MBAR',whichMBAR);
  49.     
  50.     if (mbarResource)
  51.         {
  52.         UInt16    menuCount = (**mbarResource).numberOfMenus;
  53.         UInt16    menuIndex = 0;
  54.         
  55.         HLock((Handle) mbarResource);
  56.         
  57.         while (menuCount--)
  58.             {
  59.             SInt16    whichMenu = (**mbarResource).menuIDList[menuIndex];
  60.             MenuRef    theMenu;
  61.  
  62.             //    try to make the MenuRef from a 'CMNU' which allows us to
  63.             //    automatically register any commands we find in the resource.
  64.             
  65.             theMenu = this->GetMenuFromCMNU(whichMenu);
  66.             if (theMenu == NULL)
  67.                 {
  68.                 //    no 'CMNU' was found, so go ahead and use a 'MENU'
  69.                 //    resource, knowing that we must register commands
  70.                 //    manually.
  71.                 
  72.                 theMenu = GetMenu(whichMenu);
  73.                 }
  74.  
  75.             //    Add the menu to the end of the menubar
  76.             if (theMenu)
  77.                 InsertMenu(theMenu,0);
  78.             else
  79.                 return resNotFound;
  80.  
  81.             menuIndex++;
  82.             }
  83.         
  84.         //    force a redraw of the menubar at the next possible opportunity
  85.         
  86.         InvalMenuBar();
  87.         
  88.         HUnlock((Handle) mbarResource);
  89.         ReleaseResource((Handle) mbarResource);
  90.         }
  91.     else
  92.         return resNotFound;
  93.         
  94.     return noErr;
  95.     }
  96.  
  97.  
  98. //    Define some functions to help us walk through CMNU resources
  99. //    (this should make the code a bit more readable)
  100.  
  101. static MenuCommandID *FindMenuCommandPtrFromCMNUItem(CMNUItemData *currentItem);
  102. static CMNUItemData *FindNextCMNUItem(CMNUItemData *currentItem);
  103.  
  104.  
  105. static MenuCommandID *
  106. FindMenuCommandPtrFromCMNUItem(CMNUItemData *currentItem)
  107.     {
  108.     Byte * p = (Byte *) currentItem;
  109.     
  110.     if ((*p) == NULL)        //    we’re at the end of the CMNU!
  111.         return NULL;
  112.     
  113.     p +=        (*p) + 1        //    itemString[0], a.k.a. the length
  114.             +    sizeof(Byte)    //    itemIcon
  115.             +    sizeof(Byte)    //    itemCmd
  116.             +    sizeof(Byte)    //    itemMark
  117.             +    sizeof(Style);    //    itemStyle
  118.     p = (Byte *) ((((long) p) + 1) & ~1);    //    align up to the next even boundary
  119.     
  120.     return (MenuCommandID *) p;
  121.     }
  122.  
  123.  
  124. static CMNUItemData *
  125. FindNextCMNUItem(CMNUItemData *currentItem)
  126.     {
  127.     return (CMNUItemData *)
  128.             (FindMenuCommandPtrFromCMNUItem(currentItem) + 1);
  129.     }
  130.  
  131.  
  132. MenuRef
  133. TMenuBar::GetMenuFromCMNU(short whichMenu)
  134.     {
  135.     CMNUResource ** theCMNU = (CMNUResource **) GetResource('CMNU',whichMenu);
  136.     MenuRef            newMenuRef = NULL;
  137.  
  138.     if (theCMNU)
  139.         {
  140.         HLock((Handle) theCMNU);
  141.  
  142.         MenuID            theMenuID = (**theCMNU).menuID;
  143.         MenuItemID        itemNum = 1;
  144.         MenuCommandID    theCommand;
  145.         
  146.         //    Make a new MenuRef from the CMNU data, eh?
  147.         newMenuRef = NewMenu(theMenuID,(**theCMNU).menuTitle);
  148.  
  149.         //    MENU & CMNU resources suck, don’t they?
  150.         Byte * p = (Byte *) (**theCMNU).menuTitle;
  151.  
  152.         //    Don’t forget to skip past string and length byte
  153.         p += *p + 1;
  154.  
  155.         CMNUItemData * theItemData = (CMNUItemData *) p;
  156.         
  157.         while (theItemData->itemString[0])        //    do we have any menu items
  158.             {
  159.             p = (Byte *) theItemData;
  160.             p += *p +1;
  161.             
  162.             //    use the item data to build a new menuitem
  163.             AppendMenu(newMenuRef,theItemData->itemString);
  164.             SetItemIcon(newMenuRef,itemNum,*p++);
  165.             SetItemCmd(newMenuRef,itemNum,*p++);
  166.             SetItemMark(newMenuRef,itemNum,*p++);
  167.             SetItemStyle(newMenuRef,itemNum,*p++);
  168.  
  169.             //    deal with any disabled items
  170.             if (!((**theCMNU).enableFlags & (1 << itemNum)))
  171.                 DisableItem(newMenuRef,itemNum);
  172.  
  173.             //    align up to the next even boundary
  174.             p = (Byte *) ((((long) p) + 1) & ~1);
  175.             
  176.             //    register the menu command, if any
  177.             theCommand = *((MenuCommandID *) p);
  178.             if (theCommand)
  179.                 this->RegisterCommand(theCommand,theMenuID,itemNum);
  180.  
  181.             theItemData = FindNextCMNUItem(theItemData);
  182.             itemNum++;
  183.             }
  184.  
  185.         ReleaseResource((Handle) theCMNU);
  186.         }
  187.  
  188.     return newMenuRef;
  189.     }
  190.  
  191.  
  192. //    menu command mapping functions
  193.  
  194. //    find the menu command in the array, given the menu and item
  195.  
  196. MenuCommandID
  197. TMenuBar::GetCommand(MenuID menu, MenuItemID item)
  198.     {
  199.     MenuMapping        key = {menu,item,kNoMenuCommandID};
  200.     MenuMapping    *    foundMapping;
  201.     
  202.     foundMapping = (MenuMapping *) fMenuItemTable.Find(&key);
  203.  
  204.     if (foundMapping)
  205.         return foundMapping->fCommand;
  206.         
  207.     return kNoMenuCommandID;
  208.     }
  209.  
  210.  
  211. //    find the menu and item in the array, given the menu command
  212.     
  213. void
  214. TMenuBar::GetMenuAndItem(MenuCommandID commandNum, MenuID * returnedMenu, MenuItemID * returnedItem)
  215.     {
  216.     MenuMapping        key = {kNoMenuID,kNoMenuItemID,commandNum};
  217.     MenuMapping    *    foundMapping;
  218.  
  219.     foundMapping = (MenuMapping *) fCommandTable.Find(&key);
  220.  
  221.     if (foundMapping)
  222.         {
  223.         *returnedMenu = foundMapping->fMenu;
  224.         *returnedItem = foundMapping->fItem;
  225.         }
  226.     else
  227.         {
  228.         *returnedMenu = kNoMenuID;
  229.         *returnedItem = kNoMenuItemID;
  230.         }
  231.     }
  232.  
  233.  
  234. OSErr
  235. TMenuBar::RegisterCommand(MenuCommandID commandNum, MenuID menu, MenuItemID item)
  236.     {
  237.     MenuMapping    * aMapping = new MenuMapping;
  238.     
  239.     if (aMapping == NULL)
  240.         return MemError();
  241.         
  242.     aMapping->fMenu = menu;
  243.     aMapping->fItem = item;
  244.     aMapping->fCommand = commandNum;
  245.     
  246.     fCommandTable.Add(aMapping);
  247.     fMenuItemTable.Add(aMapping);
  248.     
  249.     return noErr;
  250.     }
  251.  
  252.  
  253. OSErr
  254. TMenuBar::UnregisterCommand(MenuCommandID commandNum)
  255.     {
  256.     MenuMapping    key = {kNoMenuID,kNoMenuItemID,commandNum};
  257.     
  258.     return noErr;
  259.     }
  260.     
  261.     
  262. //    menu enable/disable routines for menu items
  263.  
  264. MenuHandle
  265. TMenuBar::GetMenuHandleAndItemFromCommand(MenuCommandID commandNum, MenuID *menu, MenuItemID *item)
  266.     {
  267.     this->GetMenuAndItem(commandNum,menu,item);
  268.     if (*menu != kNoMenuID)
  269.         return GetMenuHandle(*menu);
  270.     else
  271.         return NULL;
  272.     }
  273.  
  274.  
  275. void
  276. TMenuBar::EnableCommand(MenuCommandID commandNum, Boolean enable)
  277.     {
  278.     MenuHandle        menuHandle;
  279.     MenuID            menu;
  280.     MenuItemID        item;
  281.     
  282.     menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
  283.     if (menuHandle)
  284.         {
  285.         if (enable)
  286.             EnableItem(menuHandle,item);
  287.         else
  288.             DisableItem(menuHandle,item);
  289.         }
  290.     }
  291.  
  292.     
  293. void
  294. TMenuBar::EnableAndCheckCommand(MenuCommandID commandNum, Boolean enable, Boolean check)
  295.     {
  296.     MenuHandle        menuHandle;
  297.     MenuID            menu;
  298.     MenuItemID        item;
  299.     
  300.     menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
  301.     if (menuHandle)
  302.         {
  303.         CheckItem(menuHandle,item,check);
  304.  
  305.         if (enable)
  306.             EnableItem(menuHandle,item);
  307.         else
  308.             DisableItem(menuHandle,item);
  309.         }
  310.     }
  311.  
  312.  
  313. void
  314. TMenuBar::GetItemString(MenuCommandID commandNum,StringPtr itemString)
  315.     {
  316.     MenuHandle        menuHandle;
  317.     MenuID            menu;
  318.     MenuItemID        item;
  319.     
  320.     menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
  321.     if (menuHandle)
  322.         GetMenuItemText(menuHandle,item,itemString);
  323.     }
  324.  
  325.     
  326. void
  327. TMenuBar::SetItemString(MenuCommandID commandNum,StringPtr itemString)
  328.     {
  329.     MenuHandle        menuHandle;
  330.     MenuID            menu;
  331.     MenuItemID        item;
  332.     
  333.     menuHandle = this->GetMenuHandleAndItemFromCommand(commandNum,&menu,&item);
  334.     if (menuHandle)
  335.         SetMenuItemText(menuHandle,item,itemString);
  336.     }
  337.     
  338.  
  339. Boolean    TMenuBar::fgMenuBarHidden = false;
  340.  
  341.  
  342. /* static */ void
  343. TMenuBar::HideMenuBar()
  344.     {
  345.     }
  346.  
  347.  
  348. /* static */ void
  349. TMenuBar::ShowMenuBar()
  350.     {
  351.     }
  352.  
  353.  
  354. /* static */ void
  355. TMenuBar::EnterModalState()
  356.     {
  357.     }
  358.  
  359.  
  360. /* static */ void
  361. TMenuBar::ExitModalState()
  362.     {
  363.     }
  364.